<?php
require_once(dirname(__FILE__)."/_abstract_/Component.php");
require_once(dirname(__FILE__)."/Servlet.php");
require_once(dirname(__FILE__)."/Configuration.php");
require_once(dirname(__FILE__)."/Session.php");
require_once(dirname(__FILE__)."/Cookie.php");
require_once(dirname(__FILE__)."/Request.php");
require_once(dirname(__FILE__)."/Response.php");
require_once(dirname(__FILE__)."/Models.php");

/**
 * Implements front controller MVC functionality. This is ServletsAPI focal point, integrating all components as a whole. Components it integrates are:
 * - configuration: gathers information about application from an XML file
 * - session: gathers information about user session from $_SESSION, then performs all operations on session via this class.
 * - cookie: gathers information about user cookie from $_COOKIE, then performs all operations on cookie via this class.
 * - request: gathers information about user request from $_SERVER, $_GET, $_POST, $_FILES. Normally, once detected, there is no need to change it, but such a possibility exists.
 * - response: gathers information for server response
 * - models: gathers information from models queried by page controller.
 * Page controller is located via ControllerLocator helper based on page requested (so it is page-specific) and page information defined in PAGES tag @ configuration file and its 
 * main purpose is to fill models attributes factory.
 * 
 * Each component minus models can be followed by a listener, in which you are able to fine-tune whatever API detected in previous step and add/remove/modify attributes. Listeners 
 * are not mandatory and not part of ServletsAPI, since by their very nature they implement application-specific customizations of ServletsAPI. In order to be detected, a 
 * LISTENERS_PATH must be defined and all listeners must be located there at paths set in XML configuration file (tag "listeners", subtag (component), eg listeners.session). 
 * 
 * These listeners' scopes are:
 * - application: defines application constants and performs other application-level generic behavior, which is why it runs before components are detected.
 * - configuration: performs application-level changes to configuration object
 * - session: performs application-level changes to session object, as for example saving certain request parameters directly to session
 * - cookie: performs application-level changes to cookie object
 * - request: performs application-level changes of request, usually in form of authentication.
 * - response: performs application-level changes to session object
 * If one needs page-level changes in any of these, it must be implemented by page controller.
 * 
 * After models are set, response is performed in three steps:
 * - building: a wrapper is called to manage detected response content-type, set up specific headers and generate response output buffer, then saved to ResponseStream
 * - filtering (optional): response listener is called to operate global changes on ResponseStream. Good examples why we frequently need to modify response after it's generated are:
 * 		1. a View Expression Language parsing that makes possible to clear HTML views of variable-level scripting.
 * 		2. a View Tag Language parsing that makes possible to clear HTML views of function-level scripting.
 * - committing: sets content type, sends headers and shows response back to client
 */
class FrontController {	
	/**
	 * Performs all steps described in class documentation
	 * 
	 * @throws ServletException
	 */
	public function __construct() {
		// performs application-level non-configurative settings
		Component::runListener("application"); 
		
		// get configuration object
		if(!defined("CONFIGURATION_PATH")) throw new ServletException("CONFIGURATION_PATH not defined!");
		Servlet::$configuration = new Configuration(CONFIGURATION_PATH);
		
		// operates custom changes of configuration object
		Component::runListener("configuration");
		
		// sets session object
		Servlet::$session = new Session();		
		
		// operates custom changes of session object
		Component::runListener("session");
		
		// sets cookie object
		Servlet::$cookie = new Cookie();
		
		// operates custom changes of cookie object
		Component::runListener("cookie");
		
		// sets request object
		Servlet::$request = new Request(); 
		
		// operates custom changes of request object (eg. authentication)
		Component::runListener("request");
		
		// sets response object
		Servlet::$response = new Response();
		
		// sets models object
		Servlet::$models = new Models();
		
		// runs controller
		Component::runController();
		
		// builds response
		Servlet::$response->build();
		
		// operates custom changes on response
		Component::runListener("response");
							
		// commits response
		Servlet::$response->commit();		
	}
}